import { defaultTableStyle } from './default-style';
import { checkInTriangle } from './comm-method';

export const fontStyle = {
  //fontFamily: 'Verdana;serif',
  //对齐方式
  textAlign: 'middle',
  dominantBaseline: 'middle',
  //字体
  fontFamily: 'arial',
  //斜体
  fontStyle: 'italic',
  //加粗
  fontWeight: 'bold',
  //下划线 underline，上划线 overline, 删除线 line-through
  textDecoration: 'underline',
  //大小
  fontSize: 24,
  //填充颜色
  fill: 'red',
  //边框颜色
  //stroke: 'red',
  //调整间距
  //letterSpacing: 8,
  //
  textLength: 120,
  //textAnchor: 'left',
  //自适应宽度 spacing
  lengthAdjust: 'spacing',
};
export const pathType = {
  //M,L,H,V,l,h,v,Z
  M: { code: 'M', desc: 'moveto' }, //移动到
  Rm: { code: 'm', desc: 'rMoveto' }, //相对坐标移动到
  L: { code: 'L', desc: 'lineto' }, //直线到
  Rl: { code: 'l', desc: 'rLineto' }, //相对坐标画直线到
  H: { code: 'H', desc: 'horizontalLineto' }, //水平直线到
  Rh: { code: 'h', desc: 'rHorizontalLineto' }, //水平相对坐标画直线到
  V: { code: 'V', desc: 'verticalLineto' }, //垂直到
  Rv: { code: 'v', desc: 'rVerticalLineto' }, //垂直相对坐标画直线到
  Z: { code: 'Z', desc: 'closepath' }, //关闭路径
};
export const drawType = {
  RECT: '矩形',
  TRIANGLE: '三角形',
  CIRCLE: '圆形',
  ELLIPSE: '椭圆',
  LINE: '直线',
  POLYGON: '多边形',
  POLYLINE: '折线',
  PATH: '路径',
  TEXT: '文字',
  ARC: '弧形',
  TABLE: '表格',
  LIMIT: '缩放平移限制',
  IMAGE: '图片',
};

export function rect(x = 0, y = 0, w = 0, h = 0, style) {
  return new Rect(x, y, w, h, style);
}

export function image(x = 0, y = 0, w = 100, h = 80, href, rotate = 0) {
  return new Image(x, y, w, h, href, rotate);
}
export function limit(x, y, w, h) {
  return new Limit(x, y, w, h);
}

export function triangle(x1, y1, x2, y2, x3, y3, style) {
  return new Triangle(x1, y1, x2, y2, x3, y3, style);
}

export function circle(ox, oy, r, style) {
  return new Circle(ox, oy, r, style);
}

export function arc(ox, oy, r, style) {
  return new Arc(ox, oy, r, style);
}

export function ellipse(ox, oy, rx, ry, style) {
  return new Ellipse(ox, oy, rx, ry, style);
}

export function line(x1, y1, x2, y2, style) {
  return new Line(x1, y1, x2, y2, style);
}

export function polygon(points, style) {
  return new Poly(drawType.POLYGON, points, style);
}

export function polyline(points, style) {
  return new Poly(drawType.POLYLINE, points, style);
}

export function path(d, style) {
  return new Path(d, style);
}

export function text(x, y, text, fontStyle) {
  return new Text(x, y, text, fontStyle);
}

export function table(x, y, w, h) {
  return new Table(x, y, w, h);
}

class Base {
  id; //类型：字符串    id
  start; //类型：数组     矩形起点坐标,值同[x,y]
  end; //类型：数组     矩形结束点坐标，值同[x+w,y+h]
  name; //类型：字符串   节点名称
  text; //类型：字符串   矩形中的文字
  style; //类型：对象     矩形样式:默认设定样式，动态样式可以使用 checkStyle函数设定
  fontStyle; //类型：对象     文字样式
  rotate; //类型：数字     旋转角度： 单位：角度（°）
  globalTranslate=[ 0, 0]; //类型： 数组，全局偏移
  translate; //类型：数组     偏移坐标：[tx,ty]，分别在x,y方向的偏移，或者说是以 tx,ty作为新的原点开始画图
  scale = 1; //类型：数字     整体缩放，（使用画图工具自带的缩放属性）默认1，也可用于自适应缩放，
  //initScale = 1; //类型： 数字     初始化缩放，用于自适应页面大小时所用的缩放参数，本质是缩放坐标，长度。不缩放线宽，字号
  totalScale = 1; //类型：数字     缩放，当使用滚轮缩放时，累计缩放量，
  isBorderScale = true; //类型：布尔     边框即线宽是否缩放，默认true
  isTextScale = true; //类型：布尔     文字是否缩放，默认true
  isClearParentStyle; //类型：布尔     是否清除父级样式，默认false
  movable = true; //类型：布尔     是否可以移动，只有全局移动时有效，默认可移动
  movableX = true; //类型：布尔     是否可以X轴移动，
  movableY = true; //类型：布尔     是否可以Y轴移动，
  zoomAble = true; //类型：布尔     是否可以缩放，只有全局缩放时有效，默认可缩放
  zoomAbleX = true; //类型：布尔     是否缩放X
  zoomAbleY = true; //类型：布尔     是否缩放Y
  isIgnoreMouseOver = false; //类型：布尔  是否忽略mouseOver检查：d对于有重叠的图形时可以设置
  onClick; //类型：函数     点击事件 参数： { event: e ,drawParam: drawParam}
  onMouseover; //类型：函数     鼠标移入图形 参数：{ event: event,drawParam: drawParam }
  onMousemove; //类型：函数     鼠标在图形上移动 参数： { event: event,drawParam: drawParam }
  onMouseout; //类型：函数     鼠标移出图形 参数：{ event: event,drawParam: drawParam }
  checkHide; //类型：函数     是否隐藏 参数：{ drawParam: drawParam } ， 返回 true / false
  checkStyle; //类型：函数     实时刷新时动态样式重置回调方法，可以通过此方法动态设定样式  参数：{drawParam: drawParam,values: values}，  返回样式的对象{}
  checkFontStyle; //类型：函数     实时刷新时动态样式重置回调方法，可以通过此方法动态设定文字样式  参数：{drawParam: drawParam,values: values}，  返回样式的对象{}
  constructor(style) {
    if (!style) {
      style = {};
    }
    this.style = style;
  }
  ignoreMouseover(){
    this.isIgnoreMouseOver = true;
    return this;
  }
  setGlobalTranslate(globalTranslate){
    if(globalTranslate){
      this.globalTranslate = globalTranslate;
    }
    return this;
  }
  setMovable(b) {
    this.movable = b;
    return this;
  }
  setMovableX(b) {
    this.movableX = b;
    return this;
  }
  setMovableY(b) {
    this.movableY = b;
    return this;
  }
  setZoomAble(b) {
    this.zoomAble = b;
    return this;
  }
  setZoomAbleX(b) {
    this.zoomAbleX = b;
    return this;
  }
  setZoomAbleY(b) {
    this.zoomAbleY = b;
    return this;
  }
  setScale(scale) {
    this.scale = scale;
    return this;
  }

  setId(id) {
    this.id = id;
    return this;
  }

  borderScale(b) {
    this.isBorderScale = b;
    return this;
  }

  textScale(b) {
    this.isTextScale = b;
    return this;
  }

  clearParentStyle(b) {
    this.isClearParentStyle = b;
    return this;
  }

  setTransform(rotate, tx, ty) {
    this.rotate = rotate;
    this.translate = [tx, ty];
    return this;
  }

  setRotate(rotate) {
    this.rotate = rotate;
    return this;
  }

  setTranslate(tx, ty) {
    this.translate = [tx, ty];
    return this;
  }

  setStyle(style) {
    this.style = style;
    return this;
  }

  setStart(start) {
    this.start = start;
    return this;
  }

  setEnd(end) {
    this.end = end;
    return this;
  }

  setName(name) {
    this.name = name;
    return this;
  }

  setText(text, fontStyle) {
    this.text = text;
    if (!fontStyle) {
      fontStyle = {};
    }
    this.fontStyle = fontStyle;
    return this;
  }

  setFontStyle(fontStyle) {
    this.fontStyle = fontStyle;
    return this;
  }

  /**
   * 检查鼠标当前坐标是否在图形内
   * @param x
   * @param y
   */
  checkMouseOver(x, y) {
    if(this.isIgnoreMouseOver){
      return false;
    }
    if (!this.start || !this.end) {
      return false;
    }
    let btnMinX = this.start[0];
    let btnMaxX = this.end[0];
    let btnMinY = this.start[1];
    let btnMaxY = this.end[1];
    return x >= btnMinX && x <= btnMaxX && y >= btnMinY && y <= btnMaxY;
  }

  scaleTo(old, clickPoint, scale) {
    return clickPoint - (clickPoint - old) * scale;
  }

  moveStartEnd(deltaX, deltaY) {
    if (this.start) {
      if (this.movableX) {
        this.start[0] += deltaX;
      }
      if (this.movableY) {
        this.start[1] += deltaY;
      }
    }
    if (this.end) {
      if (this.movableX) {
        this.end[0] += deltaX;
      }
      if (this.movableY) {
        this.end[1] += deltaY;
      }
    }
  }

  zoomStartEnd(cx, cy, scale) {
    if (this.start) {
      if (this.zoomAbleX) {
        this.start[0] = this.scaleTo(this.start[0], cx, scale);
      }
      if (this.zoomAbleY) {
        this.start[1] = this.scaleTo(this.start[1], cy, scale);
      }
    }
    if (this.end) {
      if (this.zoomAbleX) {
        this.end[0] = this.scaleTo(this.end[0], cx, scale);
      }
      if (this.zoomAbleY) {
        this.end[1] = this.scaleTo(this.end[1], cy, scale);
      }
    }
  }
}

//多边形（自动封闭）或折线（自动封闭）
class Poly extends Base {
  type; // drawType.POLYLINE ,drawType.POLYGON
  points; //类型：字符串   点坐标xy之间用逗号隔开，点之间用空格 'x1,y1 x2,y2 x3,y3 x4,y4'
  pointList; //多边形的点坐标列表,按顺序：  [[x1,y1],[x2,y2],...] points，pointList任选其一
  constructor(type, points, style) {
    super(style);
    this.type = type;
    this.points = points;
    this.pointList = [];
    if (points) {
      points.split(' ').forEach((p) => {
        if (p) {
          let pxy = p.split(',');
          this.pointList.push([Number.parseInt(pxy[0]), Number.parseInt(pxy[1])]);
        }
      });
    }
  }

  setPointList(pointList) {
    this.pointList = pointList;
    return this;
  }

  addPoint(point) {
    this.pointList.push(point);
    return this;
  }

  addPointList(pointList) {
    this.pointList.push(...pointList);
    return this;
  }

  getPositionAttribute(attr) {
    if (!attr) {
      attr = {};
    }
    this.points = '';
    this.pointList.forEach((point) => {
      this.points += point[0] + ',' + point[1] + ' ';
    });
    attr.points = this.points;

    if (!this.start) {
      let sumX = 0;
      let sumY = 0;
      let pointCount = this.pointList.length;
      this.pointList.forEach((p) => {
        sumX += p[0];
        sumY += p[1];
      });
      this.start = [sumX / pointCount, sumY / pointCount];
    }
    if (!this.end) {
      this.end = [...this.start];
    }
  }

  checkMouseOver(x, y) {
    if(this.isIgnoreMouseOver){
      return false;
    }
    //todo 多边形，折线 判断点是否在图形内需要重写方法。默认用的 start end 矩形框范围
    return super.checkMouseOver(x, y);
  }

  // 移动
  move(deltaX, deltaY) {
    this.pointList.forEach((p) => {
      if (this.movableX) {
        p[0] += deltaX;
      }
      if (this.movableY) {
        p[1] += deltaY;
      }
    });
    this.moveStartEnd(deltaX, deltaY);
  }

  // s缩放
  zoom(cx, cy, scale, totalScale) {
    this.totalScale = totalScale;
    this.pointList.forEach((p) => {
      if (this.zoomAbleX) {
        p[0] = this.scaleTo(p[0], cx, scale);
      }
      if (this.zoomAbleY) {
        p[1] = this.scaleTo(p[1], cy, scale);
      }
    });
    this.zoomStartEnd(cx, cy, scale);
  }
}

class Table extends Base {
  type = drawType.TABLE; //图形类型：     矩形
  x; //类型：数字     矩形起点x坐标
  y; //类型：数字     矩形起点y坐标
  w; //类型：数字     矩形宽度
  h; //类型：数字     矩形高度
  title; //类型：对象     表格标题信息
  header; //类型：对象     表格表头信息
  content; //类型：对象     表格内容信息样式
  column; //类型：数组对象  表格列信息
  data; //类型：数组对象  表格数据
  rowStyle; //类型：函数     行样式回调方法
  cellStyle; //类型：函数     单元格样式回调方法
  cellClick; //类型：函数     单元格点击事件回调方法
  tableDrawList; //类型：数组     表格的子组件
  constructor(x = 0, y = 0, w = 0, h = 0) {
    super();
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.content = {};
  }

  setColumn(column) {
    this.column = column;
    return this;
  }

  setData(data) {
    this.data = data;
    return this;
  }

  setTitle({ text, height, border, tableStyle, fontStyle }) {
    this.title = {
      text: text,
      height: height,
      border: border,
      tableStyle: tableStyle,
      fontStyle: fontStyle,
    };
    return this;
  }

  setTitleText(titleText) {
    if (!this.title) {
      this.title = {};
    }
    this.title.text = titleText;
    return this;
  }

  setTitleHeight(titleHeight) {
    if (!this.title) {
      this.title = {};
    }
    this.title.height = titleHeight;
    return this;
  }

  setTitleBorder(titleBorder) {
    if (!this.title) {
      this.title = {};
    }
    this.title.border = titleBorder;
    return this;
  }

  setTitleTableStyle(titleTableStyle) {
    if (!this.title) {
      this.title = {};
    }
    this.title.tableStyle = titleTableStyle;
    return this;
  }

  setTitleFontStyle(titleFontStyle) {
    if (!this.title) {
      this.title = {};
    }
    this.title.fontStyle = titleFontStyle;
    return this;
  }

  setHeader({ height, tableStyle, fontStyle }) {
    this.header = {
      height: height,
      tableStyle: tableStyle,
      fontStyle: fontStyle,
    };
    return this;
  }

  setHeaderHeight(headerHeight) {
    if (!this.header) {
      this.header = {};
    }
    this.header.height = headerHeight;
    return this;
  }

  setHeaderTableStyle(headerTableStyle) {
    if (!this.header) {
      this.header = {};
    }
    this.header.tableStyle = headerTableStyle;
    return this;
  }

  setHeaderFontStyle(headerFontStyle) {
    if (!this.header) {
      this.header = {};
    }
    this.header.fontStyle = headerFontStyle;
    return this;
  }

  setContent({ tableStyle, fontStyle }) {
    this.content = {
      tableStyle: tableStyle,
      fontStyle: fontStyle,
    };
    return this;
  }

  setContentTableStyle(contentTableStyle) {
    this.content.tableStyle = contentTableStyle;
    return this;
  }

  setContentFontStyle(contentFontStyle) {
    this.content.fontStyle = contentFontStyle;
    return this;
  }

  getTableDrawList() {
    this.tableDrawList = drawTable(this);
    this.tableDrawList.forEach((d) => {
      d.setMovableX(this.movableX);
      d.setMovable(this.movableY);
      d.setZoomAbleX(this.zoomAbleX);
      d.setZoomAbleY(this.zoomAbleY);
      d.borderScale(this.isBorderScale);
      d.setScale(this.scale);
      d.textScale(this.isTextScale);
    });
    return this.tableDrawList;
  }

  // 移动
  move(deltaX, deltaY) {
    if (this.movableX) {
      this.x += deltaX;
    }
    if (this.movableY) {
      this.y += deltaY;
    }
    this.setStart([this.x, this.y]).setEnd([this.x + this.w, this.y + this.h]);
    /*this.tableDrawList.forEach(d => {
        if(d.move){
            d.move(deltaX,deltaY);
        }
    });*/
  }

  // s缩放
  zoom(cx, cy, scale, totalScale) {
    this.totalScale = totalScale;
    if (this.zoomAbleX) {
      this.x = cx - (cx - this.x) * scale;
      this.w *= scale;
    }
    if (this.zoomAbleY) {
      this.y = cy - (cy - this.y) * scale;
      this.h *= scale;
    }
    this.setStart([this.x, this.y]).setEnd([this.x + this.w, this.y + this.h]);
  }
}

function drawTable(tableDrawParam) {
  //1.计算起点以及表格长宽
  let startX = tableDrawParam.x;
  let startY = tableDrawParam.y;
  let width = tableDrawParam.w;
  let height = tableDrawParam.h;
  if (tableDrawParam.start) {
    startX = tableDrawParam.start[0];
    startY = tableDrawParam.start[1];
  } else {
    tableDrawParam.start = [startX, startY];
  }
  if (tableDrawParam.end) {
    width = tableDrawParam.end[0] - startX;
    height = tableDrawParam.end[1] - startY;
  } else {
    tableDrawParam.end = [startX + width, startY + height];
  }

  //使用相对坐标后，把起点置0
  startX = 0;
  startY = 0;
  let drawList = [];
  let title = tableDrawParam.title;
  if (title) {
    //画title框
    let titleHeight = defaultTableStyle.title.height;
    if (title.height) {
      titleHeight = title.height;
    }
    if(tableDrawParam.zoomAbleY){
      titleHeight *= tableDrawParam.totalScale;
    }
    if (title.border || title.tableStyle) {
      let borderStyle = Object.assign({}, defaultTableStyle.title.tableStyle, title.tableStyle);
      let titleBorder = new Rect(startX, startY, width, titleHeight, borderStyle);
      drawList.push(titleBorder);
    }
    //标题
    let titleFontStyle = Object.assign({}, defaultTableStyle.title.fontStyle, title.fontStyle);
    let titleText = new Text((startX + width) / 2, (startY + titleHeight) / 2 + 2, title.text, titleFontStyle);
    drawList.push(titleText);
    startY += titleHeight;
  }
  let column = tableDrawParam.column;
  let headerColWidthArray = calColWidth(column, width);
  let columnArray = [];
  let columnWidthArray = [];
  column.forEach((col, index) => {
    let headerColWidth = headerColWidthArray[index];
    if (col.children) {
      let childrenHeaderWidthArray = calColWidth(col.children, headerColWidth);
      columnWidthArray.push.apply(columnWidthArray, childrenHeaderWidthArray);
      headerColWidthArray[index] = [headerColWidth, childrenHeaderWidthArray];
      columnArray.push.apply(columnArray, col.children);
    } else {
      columnWidthArray.push(headerColWidth);
      columnArray.push(col);
    }
  });

  let header = tableDrawParam.header;
  if (header) {
    //画表头
    let headerHeight = defaultTableStyle.header.height;
    if (header.height) {
      headerHeight = header.height;
    }
    if (tableDrawParam.zoomAbleY) {
      headerHeight *= tableDrawParam.totalScale;
    }
    //画表头
    let offsetX = 0;
    column.forEach((headRow1, index1) => {
      let headerRowHeight = headerHeight;
      let rowId = tableDrawParam.id + '-hc' + index1;
      if (headRow1.children) {
        headerRowHeight = headerHeight / 2;
        let rectRow0 = new Rect(offsetX, startY, headerColWidthArray[index1][0], headerRowHeight);
        let rectStyle = Object.assign({}, defaultTableStyle.header.tableStyle, header.tableStyle);
        let colFontStyle = Object.assign({}, defaultTableStyle.header.fontStyle, header.fontStyle);
        rectRow0.setStyle(rectStyle).setText(headRow1.label, colFontStyle);
        drawList.push(rectRow0);

        let offsetX1 = 0;
        headRow1.children.forEach((headRow2, index2) => {
          let rectRow2Col = new Rect(
              offsetX + offsetX1,
              startY + headerRowHeight,
              headerColWidthArray[index1][1][index2],
              headerRowHeight
          );
          let rectStyle2 = Object.assign({}, defaultTableStyle.header.tableStyle, header.tableStyle);
          let colFontStyle2 = Object.assign({}, defaultTableStyle.header.fontStyle, header.fontStyle);
          rectRow2Col.setStyle(rectStyle2).setText(headRow2.label, colFontStyle2);
          offsetX1 += rectRow2Col.w;
          drawList.push(rectRow2Col);
        });
        offsetX += rectRow0.w;
      } else {
        let rectRow0 = new Rect(offsetX, startY, headerColWidthArray[index1], headerRowHeight);
        let rectStyle = Object.assign({}, defaultTableStyle.header.tableStyle, header.tableStyle);
        let colFontStyle = Object.assign({}, defaultTableStyle.header.fontStyle, header.fontStyle);
        rectRow0.setStyle(rectStyle).setText(headRow1.label, colFontStyle).setId(rowId);
        drawList.push(rectRow0);
        offsetX += rectRow0.w;
      }
    });
    startY += headerHeight;
  }
  //数据内容
  height -= startY;
  let data = tableDrawParam.data;
  if (data) {
    let rowHeight = height / data.length;
    let contentTableStyle = Object.assign({}, defaultTableStyle.content.tableStyle, tableDrawParam.content.tableStyle);
    let contentFontStyle = Object.assign({}, defaultTableStyle.content.fontStyle, tableDrawParam.content.fontStyle);
    data.forEach((row, rowIndex) => {
      //回调rowStyle
      let rowStyle = {};
      if (tableDrawParam.rowStyle) {
        rowStyle = tableDrawParam.rowStyle(row, rowIndex);
        if (!rowStyle) {
          rowStyle = {};
        }
      }
      let offsetX = startX;
      let offsetY = rowHeight * rowIndex + startY;
      columnArray.forEach((cell, colIndex) => {
        let cellStyle = {};
        if (tableDrawParam.cellStyle) {
          cellStyle = tableDrawParam.cellStyle(cell, colIndex, row, rowIndex);
          if (!cellStyle) {
            cellStyle = {};
          }
        }
        //单元格矩形样式：
        let rowSpan = cellStyle.rowSpan;
       let colSpan = cellStyle.colSpan;
        if(rowSpan === undefined){
          rowSpan = 1;
        }
        if(colSpan === undefined){
          colSpan = 1;
        }
        let cellWidth = 0;
        for(let i=0;i<rowSpan;i++){
          cellWidth +=columnWidthArray[colIndex + i];
        }

        if(rowSpan === 0 || colSpan === 0){
          //加此列上一行的宽度
          offsetX += cellWidth;
          return;
        }
        let cellRect = new Rect(offsetX, offsetY, cellWidth, rowHeight * colSpan);
        let cellRectStyle = Object.assign(
            {},
            contentTableStyle,
            rowStyle.tableStyle,
            cell.tableStyle,
            cellStyle.tableStyle
        );
        let cellFontStyle = Object.assign(
            {},
            contentFontStyle,
            rowStyle.fontStyle,
            cell.fontStyle,
            cellStyle.fontStyle
        );
        cellRect.setStyle(cellRectStyle).setText(row[cell.prop], cellFontStyle);
        cellRect.cell = { rowIndex: rowIndex, row: row, columnIndex: colIndex, column: cell };
        cellRect.parent = tableDrawParam;
        if (tableDrawParam.cellClick) {
          cellRect.onClick = tableDrawParam.cellClick;
        }
        drawList.push(cellRect);
        offsetX += cellRect.w;
      });
    });
  }
  return drawList;
}

function calColWidth(column, tableWidth) {
  let colWidth = [];
  let byWidthColcount = 0;
  let usedWidth = 0;
  let totalCol = 0;
  column.forEach((col, index) => {
    if (col.children) {
      totalCol += col.children.length;
    } else {
      totalCol++;
    }
    if (col.width) {
      colWidth[index] = col.width;
      byWidthColcount++;
      usedWidth += col.width;
    }
  });
  if (byWidthColcount === 0) {
    let w = tableWidth / totalCol;
    column.forEach((col, index) => {
      let colWeight = col.children ? col.children.length : 1;
      colWidth[index] = colWeight * w;
    });
    return colWidth;
  }
  let leftCount = column.length - byWidthColcount;
  let leftWidth = tableWidth - usedWidth;
  if (leftCount === 0) {
    //每一列都设置了宽度
    column.forEach((col, index) => {
      colWidth[index] = (col.width * tableWidth) / usedWidth;
    });
  } else if (leftWidth <= 0) {
    //有列没有设置宽度，但没有剩余宽度了，则全部使用平均值
    let w = tableWidth / column.length;
    for (let i = 0; i < column.length; i++) {
      colWidth[i] = w;
    }
  } else {
    //有没有设置宽度的列，且还有宽度
    let w = leftWidth / leftCount;
    for (let i = 0; i < column.length; i++) {
      if (!colWidth[i]) {
        colWidth[i] = w;
      }
    }
  }
  return colWidth;
}

class Arc extends Base {
  type = drawType.ARC; //图形类型：     圆弧
  ox; //类型：数字     圆心x坐标
  oy; //类型：数字     圆心y坐标
  r; //类型：数字     半径
  closeType; //类型：数字     封闭类型：1-头尾相连封闭，2-头尾跟圆心相连封闭，其它-不封闭；默认不封闭
  startArc; //类型：数字     开始弧度
  endArc; //类型：数字     结束弧度
  startAngle; //类型：数字     开始角度
  endAngle; //类型：数字     结束角度

  constructor(ox, oy, r, style) {
    super(style);
    this.ox = ox;
    this.oy = oy;
    this.r = r;
    this.start = [this.ox - this.r, this.oy];
    this.end = [this.ox + this.r, this.oy];
  }

  setArc(startArc, endArc, closeType) {
    this.startArc = startArc;
    this.endArc = endArc;
    this.closeType = closeType;
    return this;
  }

  setAngle(startAngle, endAngle, closeType) {
    this.startAngle = startAngle;
    this.endAngle = endAngle;
    this.closeType = closeType;
    this.startArc = (startAngle * Math.PI) / 180;
    this.endArc = (endAngle * Math.PI) / 180;
    return this;
  }

  setCloseType(closeType) {
    this.closeType = closeType;
    return this;
  }

  getPositionAttribute(attr) {
    if (!attr) {
      attr = {};
    }
    let bigFlag = Math.abs(this.startArc - this.endArc) > Math.PI ? 1 : 0;

    //计算起点：
    let x1 = this.ox + this.r * Math.cos(this.startArc);
    let y1 = this.oy + this.r * Math.sin(this.startArc);
    //终点
    let x2 = this.ox + this.r * Math.cos(this.endArc);
    let y2 = this.oy + this.r * Math.sin(this.endArc);
    let d = 'M' + x1 + ' ' + y1;
    d += ' A' + this.r + ' ' + this.r + ' 0 ' + bigFlag + ' 1';
    d += ' ' + x2 + ' ' + y2;
    if (this.closeType === 1) {
      d += 'Z';
    } else if (this.closeType === 2) {
      d += 'L' + this.ox + ' ' + this.oy + ' Z';
    }
    attr.d = d;
  }

  // 移动
  move(deltaX, deltaY) {
    if (this.movableX) {
      this.ox += deltaX;
    }
    if (this.movableY) {
      this.oy += deltaY;
    }
    this.moveStartEnd(deltaX, deltaY);
  }

  // s缩放
  zoom(cx, cy, scale, totalScale) {
    this.totalScale = totalScale;
    this.ox = this.scaleTo(this.ox, cx, scale);
    this.oy = this.scaleTo(this.oy, cy, scale);
    this.r *= scale;
    this.zoomStartEnd(cx, cy, scale);
  }

  //判断点在圆内： 点到圆心得距离小于半径
  checkMouseOver(x0, y0) {
    if(this.isIgnoreMouseOver){
      return false;
    }
    let distance = Math.sqrt((x0 - this.ox) * (x0 - this.ox) + (y0 - this.oy) * (y0 - this.oy));
    if (distance > this.r) {
      return false;
    }
    //计算点与圆心的弧度
    if (distance < 1) {
      return true;
    }
    let arc = Math.acos((x0 - this.ox) / distance);
    if (y0 < this.oy) {
      arc = Math.PI * 2 - arc;
    }
    let inArea = arc >= this.startArc && arc <= this.endArc;
    if (this.closeType === 2) {
      //如果是扇形圆弧 closeType == 2
      return inArea;
    }
    let bigFlag = Math.abs(this.startArc - this.endArc) > Math.PI;
    //只有 在扇形范围内时才进行下一步判断
    if (!inArea && !bigFlag) {
      return false;
    }
    let x1 = this.ox + this.r * Math.cos(this.startArc);
    let y1 = this.oy + this.r * Math.sin(this.startArc);
    //终点
    let x2 = this.ox + this.r * Math.cos(this.endArc);
    let y2 = this.oy + this.r * Math.sin(this.endArc);
    if (this.closeType === 1) {
      //如果是头尾相连 弧形区域
      let inTriangle = checkInTriangle(x0, y0, x1, y1, x2, y2, this.ox, this.oy);
      return (!bigFlag && !inTriangle) || (bigFlag && (inTriangle || inArea));
    } else if (this.style.fill && this.style.fill !== 'none') {
      //填充的也同 closeType === 1一样判断
      let inTriangle = checkInTriangle(x0, y0, x1, y1, x2, y2, this.ox, this.oy);
      return (!bigFlag && !inTriangle) || (bigFlag && inTriangle);
    } else {
      //纯弧线时，允许在误差2px内算是选中
      return this.r - distance <= 2;
    }
  }
}

class Text extends Base {
  type = drawType.TEXT; //图形类型：     文字
  x; //类型：数字     文字定位点x坐标
  y; //类型：数字     文字定位点y坐标
  children; //类型：数组     多行文字使用children
  constructor(x, y, text, fontStyle) {
    super();
    if (!fontStyle) {
      fontStyle = {};
    }
    this.fontStyle = fontStyle;
    this.x = x;
    this.y = y;
    this.text = text;
    this.start = [x, y];
    this.end = [x, y];
    this.children = [];
  }

  addText(text) {
    this.children.push(text);
    return this;
  }

  addTextList(textList) {
    this.children.push(...textList);
    return this;
  }

  getPositionAttribute(attr) {
    if (!attr) {
      attr = {};
    }
    attr.x = this.x;
    attr.y = this.y;
  }

  // 移动
  move(deltaX, deltaY) {
    if (this.movableX) {
      this.x += deltaX;
    }
    if (this.movableY) {
      this.y += deltaY;
    }
    this.moveStartEnd(deltaX, deltaY);
    if (this.children) {
      this.children.forEach((c) => {
        c.move(deltaX, deltaY);
      });
    }
  }

  // s缩放
  zoom(cx, cy, scale, totalScale) {
    this.totalScale = totalScale;
    if (this.text === '测试文字') {
      console.log(this.start, this.end);
    }
    if (this.zoomAbleX) {
      this.x = this.scaleTo(this.x, cx, scale);
    }
    if (this.zoomAbleY) {
      this.y = this.scaleTo(this.y, cy, scale);
    }
    this.zoomStartEnd(cx, cy, scale);
    if (this.text === '测试文字') {
      console.log(this.start, this.end);
    }
    if (this.children) {
      this.children.forEach((c) => {
        c.zoom(cx, cy, scale, totalScale);
      });
    }
  }

  //判断点在圆内： 点到圆心得距离小于半径
  checkMouseOver(x0, y0) {
    if(this.isIgnoreMouseOver){
      return false;
    }
    let minX = Math.min(this.x1, this.x2);
    let maxX = Math.max(this.x1, this.x2);
    let minY = Math.min(this.y1, this.y2);
    let maxY = Math.max(this.y1, this.y2);
    //在直线上
    let offset = (y0 - this.y1) * (this.x2 - this.x1) - (x0 - this.x1) * (this.y2 - this.y1);
    let check2 = offset === 0;
    //在线段范围内
    let check1 = x0 >= minX && x0 <= maxX && y0 >= minY && y0 <= maxY;
    return check1 && check2;
  }
}

/**
 M = moveto
 L = lineto
 H = horizontal lineto
 V = vertical lineto
 C = curveto
 S = smooth curveto
 Q = quadratic Bézier curve
 T = smooth quadratic Bézier curveto
 A = elliptical Arc
 Z = closepath
 */
class PathPoint {
  type; //类型：字符串    点类型，目前先支持： M,L,H,V,l,h,v,Z (小写代表相对上一点的位置)
  x;
  y;

  constructor(type, x, y) {
    this.type = type;
    this.x = x;
    this.y = y;
  }
}

class Path extends Base {
  type = drawType.PATH; //图形类型：     路径:可以不连续
  d; //类型：字符串   路径参数
  pointList;

  constructor(d, style) {
    super(style);
    this.d = d;
    this.pointList = [];
  }

  addPoint(point) {
    this.pointList.push(point);
    return this;
  }

  moveto(x, y) {
    this.addPoint(new PathPoint(pathType.M, x, y));
    return this;
  }

  movetoRxy(offsetX, offsetY) {
    this.addPoint(new PathPoint(pathType.Rm, offsetX, offsetY));
    return this;
  }

  lineto(x, y) {
    this.addPoint(new PathPoint(pathType.L, x, y));
    return this;
  }

  linetoRxy(offsetX, offsetY) {
    this.addPoint(new PathPoint(pathType.Rl, offsetX, offsetY));
    return this;
  }

  linetoX(x) {
    this.addPoint(new PathPoint(pathType.H, x));
    return this;
  }

  linetoRx(offsetX) {
    this.addPoint(new PathPoint(pathType.Rh, offsetX));
    return this;
  }

  linetoY(y) {
    this.addPoint(new PathPoint(pathType.V, undefined, y));
    return this;
  }

  linetoRy(offsetY) {
    this.addPoint(new PathPoint(pathType.Rv, undefined, offsetY));
    return this;
  }

  closepath() {
    this.addPoint(new PathPoint(pathType.Z));
    return this;
  }

  getPositionAttribute(attr) {
    if (!attr) {
      attr = {};
    }
    if (this.pointList) {
      let d = '';
      this.pointList.forEach((p) => {
        d += p.type.code;
        if (typeof p.x !== 'undefined') {
          d += p.x + ' ';
        }
        if (typeof p.y !== 'undefined') {
          d += p.y + ' ';
        }
      });
      this.d = d;
      attr.d = this.d;
    } else if (this.d) {
      attr.d = this.d;
    }
  }

  // 移动
  move(deltaX, deltaY) {
    this.pointList.forEach((p) => {
      if (p.x !== undefined && /[A-Z]/.test(p.type.code) && this.movableX) {
        p.x += deltaX;
      }
      if (p.y !== undefined && /[A-Z]/.test(p.type.code) && this.movableY) {
        p.y += deltaY;
      }
    });
    this.moveStartEnd(deltaX, deltaY);
  }

  // s缩放
  zoom(cx, cy, scale, totalScale) {
    this.totalScale = totalScale;
    this.pointList.forEach((p) => {
      if (p.x !== undefined && this.zoomAbleX) {
        if (/[A-Z]/.test(p.type.code)) {
          p.x = this.scaleTo(p.x, cx, scale);
        } else {
          p.x *= scale;
        }
      }
      if (p.y !== undefined && this.zoomAbleY) {
        if (/[A-Z]/.test(p.type.code)) {
          p.y = this.scaleTo(p.y, cy, scale);
        } else {
          p.y *= scale;
        }
      }
    });
    this.zoomStartEnd(cx, cy, scale);
  }

  //判断点在圆内： 点到圆心得距离小于半径
  checkMouseOver() {
    if(this.isIgnoreMouseOver){
      return false;
    }
    return false;
  }
}

class Line extends Base {
  type = drawType.LINE; //图形类型：     直线
  x1; //类型：数字     第一个点x坐标
  y1; //类型：数字     第一个点y坐标
  x2; //类型：数字     第二个点x坐标
  y2; //类型：数字     第二个点y坐标
  constructor(x1, y1, x2, y2, style) {
    super(style);
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
    this.start = [x1, y1];
    this.end = [x2, y2];
  }

  getPositionAttribute(attr) {
    if (!attr) {
      attr = {};
    }
    attr.x1 = this.x1;
    attr.y1 = this.y1;
    attr.x2 = this.x2;
    attr.y2 = this.y2;
  }

  // 移动
  move(deltaX, deltaY) {
    if (this.movableX) {
      this.x1 += deltaX;
      this.x2 += deltaX;
    }
    if (this.movableY) {
      this.y1 += deltaY;
      this.y2 += deltaY;
    }
    this.moveStartEnd(deltaX, deltaY);
  }

  // s缩放
  zoom(cx, cy, scale, totalScale) {
    this.totalScale = totalScale;
    if (this.zoomAbleX) {
      this.x1 = this.scaleTo(this.x1, cx, scale);
      this.x2 = this.scaleTo(this.x2, cx, scale);
    }
    if (this.zoomAbleY) {
      this.y1 = this.scaleTo(this.y1, cy, scale);
      this.y2 = this.scaleTo(this.y2, cy, scale);
    }
    this.zoomStartEnd(cx, cy, scale);
  }
}

class Ellipse extends Base {
  type = drawType.ELLIPSE; //图形类型：     椭圆
  ox; //类型：数字     圆心x坐标
  oy; //类型：数字     圆心y坐标
  rx; //类型：数字     x轴半径
  ry; //类型：数字     y轴半径

  constructor(ox, oy, rx, ry, style) {
    super(style);
    this.ox = ox;
    this.oy = oy;
    this.rx = rx;
    this.ry = ry;
    this.start = [this.ox - this.rx, this.oy];
    this.end = [this.ox + this.rx, this.oy];
  }

  getPositionAttribute(attr) {
    if (!attr) {
      attr = {};
    }
    attr.cx = this.ox;
    attr.cy = this.oy;
    attr.rx = this.rx;
    attr.ry = this.ry;
  }

  // 移动
  move(deltaX, deltaY) {
    if (this.movableX) {
      this.ox += deltaX;
    }
    if (this.movableY) {
      this.oy += deltaY;
    }
    this.moveStartEnd(deltaX, deltaY);
  }

  // s缩放
  zoom(cx, cy, scale, totalScale) {
    this.totalScale = totalScale;
    if (this.zoomAbleX) {
      this.ox = this.scaleTo(this.ox, cx, scale);
      this.rx *= scale;
    }
    if (this.zoomAbleY) {
      this.oy = this.scaleTo(this.oy, cy, scale);
      this.ry *= scale;
    }
    this.zoomStartEnd(cx, cy, scale);
  }

  //判断点在圆内： 点到圆心得距离小于半径
  checkMouseOver(x0, y0) {
    if(this.isIgnoreMouseOver){
      return false;
    }
    return (
        ((x0 - this.ox) / this.rx) * ((x0 - this.ox) / this.rx) +
        ((y0 - this.oy) / this.ry) * ((y0 - this.oy) / this.ry) <=
        1
    );
  }
}

class Circle extends Base {
  type = drawType.CIRCLE; //图形类型：     圆形
  ox; //类型：数字     圆心x坐标
  oy; //类型：数字     圆心y坐标
  r; //类型：数字     半径

  constructor(ox, oy, r, style) {
    super(style);
    this.ox = ox;
    this.oy = oy;
    this.r = r;
    this.start = [this.ox - this.r, this.oy];
    this.end = [this.ox + this.r, this.oy];
  }

  //根据直径上的两个点确定圆心以及半径
  diameterPoints(x1, y1, x2, y2) {
    this.ox = (x1 + x2) / 2;
    this.oy = (y1 + y2) / 2;
    this.r = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) / 2;
    this.start = [this.ox - this.r, this.oy];
    this.end = [this.ox + this.r, this.oy];
    return this;
  }

  getPositionAttribute(attr) {
    if (!attr) {
      attr = {};
    }
    attr.cx = this.ox;
    attr.cy = this.oy;
    attr.r = this.r;
  }

  // 移动
  move(deltaX, deltaY) {
    if (this.movableX) {
      this.ox += deltaX;
    }
    if (this.movableY) {
      this.oy += deltaY;
    }
    this.moveStartEnd(deltaX, deltaY);
  }

  // s缩放
  zoom(cx, cy, scale, totalScale) {
    this.totalScale = totalScale;
    this.ox = this.scaleTo(this.ox, cx, scale);
    this.oy = this.scaleTo(this.oy, cy, scale);
    this.r *= scale;
    this.zoomStartEnd(cx, cy, scale);
  }

  //判断点在圆内： 点到圆心得距离小于半径
  checkMouseOver(x0, y0) {
    if(this.isIgnoreMouseOver){
      return false;
    }
    let distance = Math.sqrt((x0 - this.ox) * (x0 - this.ox) + (y0 - this.oy) * (y0 - this.oy));
    return distance <= this.r;
  }
}

class Triangle extends Base {
  type = drawType.TRIANGLE; //图形类型：     三角形
  x1; //类型：数字     第一个点x坐标
  y1; //类型：数字     第一个点y坐标
  x2; //类型：数字     第二个点x坐标
  y2; //类型：数字     第二个点y坐标
  x3; //类型：数字     第三个点x坐标
  y3; //类型：数字     第三个点y坐标

  constructor(x1, y1, x2, y2, x3, y3, style) {
    super(style);
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
    this.x3 = x3;
    this.y3 = y3;
    this.start = [(this.x1 + this.x2 + this.x3) / 3, (this.y1 + this.y2 + this.y3) / 3];
    this.end = [...this.start];
  }

  //等腰三角形设置参数 topx-顶点x坐标，topy-顶点y坐标，w-底边长，h-高，direction-顶点朝向（u/d/l/r： 分别代表上下左右，默认u-上)
  isoscelesTriangle(topX, topY, w, h, direction) {
    this.x1 = topX;
    this.y1 = topY;
    if (direction === 'd') {
      this.y2 = this.y1 - w;
      this.y3 = this.y2;
      this.x2 = this.x1 - h / 2;
      this.x3 = this.x1 + h / 2;
    } else if (direction === 'l') {
      this.x2 = this.x1 + h;
      this.x3 = this.x2;
      this.y2 = this.y1 - w / 2;
      this.y3 = this.y1 + w / 2;
    } else if (direction === 'r') {
      this.x2 = this.x1 - h;
      this.x3 = this.x2;
      this.y2 = this.y1 - w / 2;
      this.y3 = this.y1 + w / 2;
    } else {
      this.y2 = this.y1 + w;
      this.y3 = this.y2;
      this.x2 = this.x1 - h / 2;
      this.x3 = this.x1 + h / 2;
    }
    this.start = [(this.x1 + this.x2 + this.x3) / 3, (this.y1 + this.y2 + this.y3) / 3];
    this.end = [...this.start];
    return this;
  }

  getPositionAttribute(attr) {
    if (!attr) {
      attr = {};
    }
    //points="220,100 300,210 170,250"
    attr.points = this.x1 + ',' + this.y1 + ' ' + this.x2 + ',' + this.y2 + ' ' + this.x3 + ',' + this.y3;
  }

  // 移动
  move(deltaX, deltaY) {
    if (this.movableX) {
      this.x1 += deltaX;
      this.x2 += deltaX;
      this.x3 += deltaX;
    }
    if (this.movableY) {
      this.y1 += deltaY;
      this.y2 += deltaY;
      this.y3 += deltaY;
    }
    this.moveStartEnd(deltaX, deltaY);
  }

  // s缩放
  zoom(cx, cy, scale, totalScale) {
    this.totalScale = totalScale;
    if (this.zoomAbleX) {
      this.x1 = this.scaleTo(this.x1, cx, scale);
      this.x2 = this.scaleTo(this.x2, cx, scale);
      this.x3 = this.scaleTo(this.x3, cx, scale);
    }
    if (this.zoomAbleY) {
      this.y1 = this.scaleTo(this.y1, cy, scale);
      this.y2 = this.scaleTo(this.y2, cy, scale);
      this.y3 = this.scaleTo(this.y3, cy, scale);
    }
    this.zoomStartEnd(cx, cy, scale);
  }

  //三角形需要重写这个判断方法
  checkMouseOver(x0, y0) {
    if(this.isIgnoreMouseOver){
      return false;
    }
    return checkInTriangle(x0, y0, this.x1, this.y1, this.x2, this.y2, this.x3, this.y3);
  }
}

class Rect extends Base {
  type = drawType.RECT; //图形类型：     矩形
  x; //类型：数字     矩形起点x坐标
  y; //类型：数字     矩形起点y坐标
  w; //类型：数字     矩形宽度
  h; //类型：数字     矩形高度
  rx;//类型：数字    x方向圆角半径
  ry;//类型：数字    y方向圆角半径
  r; //类型：数字    圆角 rx=ry时直接使用r
  leanX = 0; //类型：数字     canvas画图属性
  leanY = 0; //类型：数字     canvas画图属性
  constructor(x = 0, y = 0, w = 0, h = 0, style) {
    super(style);
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.rx = 0;
    this.ry = 0;
  }
  setRadius(r=0){
    this.r = r;
    this.rx=r;
    this.ry=r;
    return this;
  }
  setRxy(rx=0,ry=0){
    this.rx = rx;
    this.ry = ry;
    return this;
  }
  setLean(leanX, leanY) {
    this.leanX = leanX;
    this.leanY = leanY;
  }

  getPositionAttribute(attr) {
    if (!attr) {
      attr = {};
    }
    if (this.start) {
      this.x = this.start[0];
      this.y = this.start[1];
    } else {
      this.start = [this.x, this.y];
    }
    if (this.end) {
      this.w = this.end[0] - this.x;
      this.h = this.end[1] - this.y;
    } else {
      this.end = [this.x + this.w, this.y + this.h];
    }
    attr.x = this.x;
    attr.y = this.y;
    attr.width = this.w;
    attr.height = this.h;
    attr.rx = this.rx;
    attr.ry = this.ry;
  }

  // 移动
  move(deltaX, deltaY) {
    if (this.movableX) {
      this.x += deltaX;
    }
    if (this.movableY) {
      this.y += deltaY;
    }
    this.moveStartEnd(deltaX, deltaY);
  }

  // s缩放
  zoom(cx, cy, scale, totalScale) {
    this.totalScale = totalScale;
    if (this.zoomAbleX) {
      this.x = this.scaleTo(this.x, cx, scale);
      this.w *= scale;
    }
    if (this.zoomAbleY) {
      this.y = this.scaleTo(this.y, cy, scale);
      this.h *= scale;
    }
    this.zoomStartEnd(cx, cy, scale);
  }
}

class Limit extends Rect {
  type = drawType.LIMIT; // 缩放限制用，每个图形中限定最多只能出现一个
  limitStartX; //类型：数字     矩形起点x坐标限制
  limitStartY; //类型：数字     矩形起点y坐标限制
  limitEndX; //类型：数字      矩形终点x坐标限制
  limitEndY; //类型：数字     矩形终点y坐标限制
  constructor(x, y, w, h) {
    super(x, y, w, h);
    this.limitStartX = x;
    this.limitStartY = y;
    this.limitEndX = x + w;
    this.limitEndY = y + h;
    this.name = 'background';
  }
  setLimit(startX, startY, endX, endY) {
    this.limitStartX = startX;
    this.limitStartY = startY;
    this.limitEndX = endX;
    this.limitEndY = endY;
    return this;
  }
  getPositionAttribute(attr) {
    if (!attr) {
      attr = {};
    }
    if (this.start) {
      this.x = this.start[0];
      this.y = this.start[1];
    } else {
      this.start = [this.x, this.y];
    }
    if (this.end) {
      this.w = this.end[0] - this.x;
      this.h = this.end[1] - this.y;
    } else {
      this.end = [this.x + this.w, this.y + this.h];
    }
    attr.x = this.x;
    attr.y = this.y;
    attr.width = this.w;
    attr.height = this.h;
  }
  checkMove(deltaX, deltaY) {
    //console.log('移动前：', deltaX,deltaY);
    let nsx = this.x + deltaX;
    let nsy = this.y + deltaY;
    let nex = nsx + this.w;
    let ney = nsy + this.h;
    if (nsx > this.limitStartX) {
      deltaX = this.limitStartX - this.x;
    }
    if (nsy > this.limitStartY) {
      deltaY = this.limitStartY - this.y;
    }
    if (nex < this.limitEndX) {
      deltaX = this.limitEndX - this.x - this.w;
    }
    if (ney < this.limitEndY) {
      deltaY = this.limitEndY - this.y - this.h;
    }
    //console.log('移动后：', deltaX,deltaY);
    // console.log(this.limitEndY,ney);
    return { deltaX: deltaX, deltaY: deltaY };
  }
}
class Image extends Base {
  type = drawType.IMAGE; //图形类型：     图片
  x; //类型：数字     图片起点x坐标
  y; //类型：数字     图片起点y坐标
  w; //类型：数字     图片宽度
  h; //类型：数字     图片高度
  href;
  constructor(x = 0, y = 0, w = 0, h = 0, href = '') {
    super({fill: '',stroke: ''});
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.href = href;
  }
  setHref(href) {
    this.href = href;
    return this;
  }

  getPositionAttribute(attr) {
    if (!attr) {
      attr = {};
    }
    if (this.start) {
      this.x = this.start[0];
      this.y = this.start[1];
    } else {
      this.start = [this.x, this.y];
    }
    if (this.end) {
      this.w = this.end[0] - this.x;
      this.h = this.end[1] - this.y;
    } else {
      this.end = [this.x + this.w, this.y + this.h];
    }
    attr.x = this.x;
    attr.y = this.y;
    attr.width = this.w;
    attr.height = this.h;
    attr.href = this.href;
    if(this.rotate1 !== 0){
     attr.transform = `rotate(${this.rotate1})`;
    }
  }

  // 移动
  move(deltaX, deltaY) {
    if (this.movableX) {
      this.x += deltaX;
    }
    if (this.movableY) {
      this.y += deltaY;
    }
    this.moveStartEnd(deltaX, deltaY);
  }

  // s缩放
  zoom(cx, cy, scale, totalScale) {
    this.totalScale = totalScale;
    if (this.zoomAbleX) {
      this.x = this.scaleTo(this.x, cx, scale);
      this.w *= scale;
    }
    if (this.zoomAbleY) {
      this.y = this.scaleTo(this.y, cy, scale);
      this.h *= scale;
    }
    this.zoomStartEnd(cx, cy, scale);
  }
}
